package com.iwithlong.service.impl;

import com.imesne.assistant.common.bean.BeanKit;
import com.imesne.assistant.common.exception.ImesneException;
import com.imesne.assistant.common.page.PageList;
import com.imesne.assistant.common.validation.Verifier;
import com.imesne.assistant.jdbc.command.entity.Delete;
import com.imesne.assistant.jdbc.command.entity.Select;
import com.imesne.assistant.jdbc.command.entity.Update;
import com.imesne.assistant.jdbc.persist.JdbcDao;
import com.iwithlong.entity.*;
import com.iwithlong.enums.ActivityEnrollStatus;
import com.iwithlong.enums.EnrollNamelistStatus;
import com.iwithlong.service.ActivityEnrollService;
import com.iwithlong.service.ActivityService;
import com.iwithlong.service.AttendanceService;
import com.iwithlong.service.ProductSmsService;
import com.iwithlong.utils.ExcelUtils;
import com.iwithlong.vo.*;
import com.ktanx.platform.utils.HttpUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.LinkedCaseInsensitiveMap;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Created by mhy on 2018/5/1.
 */
@Service
@Transactional
public class ActivityEnrollServiceImpl implements ActivityEnrollService{

    @Resource
    private JdbcDao jdbcDao;

    @Value("${excelFilePath:null}")
    private String uploadFilePath;

    @Resource
    private AttendanceService attendanceService;

    @Resource
    private ActivityService activityService;

    @Resource
    private ProductSmsService productSmsService;


    @Override
    public PageList<ActivityEnrollVo> pageList(ActivityEnrollVo activityEnrollVo) {
        ActivityVo activityVo = null;
        MerchantVo merchantVo = null;
        Map<Long,MerchantVo> merchantVoMap = new HashMap<>();
        Select<ActivityEnroll> activityEnrollSelect = jdbcDao.createSelect(ActivityEnroll.class).where("1", 1);
        if(activityEnrollVo.getActivityVo()!=null){
            if(StringUtils.isNotBlank(activityEnrollVo.getActivityVo().getName())){
                Select<Activity> activitySelect = jdbcDao.createSelect(Activity.class).where("1",1);
                activitySelect.and("name",activityEnrollVo.getActivityVo().getName());
                Activity activity = activitySelect.singleResult();
                if(activity!=null){
                    activityEnrollSelect.and("activityId",activity.getActivityId());
                    activityVo = BeanKit.convert(new ActivityVo(),activity);
                }
            }
        }
        if(StringUtils.isNotBlank(activityEnrollVo.getStatus())){
            activityEnrollSelect.and("status",activityEnrollVo.getStatus());
        }
        if(StringUtils.isNotBlank(activityEnrollVo.getTitle())){
            activityEnrollSelect.and("title","like",new Object[]{"%"+activityEnrollVo.getTitle()+"%"});
        }
        if(activityEnrollVo.getMerchantVo()!=null){
            if(StringUtils.isNotBlank(activityEnrollVo.getMerchantVo().getMemberName())){
                Select<Merchant> merchantSelect = jdbcDao.createSelect(Merchant.class).where("1",1);
                merchantSelect.and("memberName",activityEnrollVo.getMerchantVo().getMemberName());
                Merchant merchant = merchantSelect.singleResult();
                if(merchant!=null){
                    activityEnrollSelect.and("memberId",merchant.getMemberId());
                    merchantVo = BeanKit.convert(new MerchantVo(),merchant);
                }
            }
        }
        if(activityEnrollVo.getMemberId()!=null){
            activityEnrollSelect.and("memberId",activityEnrollVo.getMemberId());
        }
        activityEnrollSelect.orderBy("gmtCreate").desc();
        PageList<ActivityEnroll> activityEnrolls = activityEnrollSelect.pageList(activityEnrollVo);
        List<ActivityEnrollVo> activityEnrollVos = BeanKit.convert(ActivityEnrollVo.class, activityEnrolls);
        PageList<ActivityEnrollVo> result = new PageList<>(activityEnrollVos,activityEnrolls.getPager());
        for (ActivityEnrollVo enrollVo : result) {
            if(merchantVo!=null){
                enrollVo.setMerchantVo(merchantVo);
            }else {
                if(merchantVoMap.get(enrollVo.getMemberId())!=null){
                    enrollVo.setMerchantVo(merchantVoMap.get(enrollVo.getMemberId()));
                }else {
                    Select<Merchant> merchantSelect = jdbcDao.createSelect(Merchant.class).where("1",1);
                    merchantSelect.and("memberId",enrollVo.getMemberId());
                    Merchant merchant = merchantSelect.singleResult();
                    if(merchant!=null){
                        MerchantVo merchantVo1 = BeanKit.convert(new MerchantVo(), merchant);
                        merchantVoMap.put(merchantVo1.getMemberId(),merchantVo1);
                        enrollVo.setMerchantVo(merchantVo1);
                    }
                }
            }
            if(activityVo!=null){
                enrollVo.setActivityVo(activityVo);
            }else {
                Select<Activity> activitySelect = jdbcDao.createSelect(Activity.class).where("1",1);
                activitySelect.and("activityId",enrollVo.getActivityId());
                Activity activity = activitySelect.singleResult();
                if(activity!=null){
                    enrollVo.setActivityVo(BeanKit.convert(new ActivityVo(),activity));
                }
            }
        }
        return result;
    }

    @Override
    public void add(ActivityEnrollVo activityEnrollVo) {
        validateActivityEnrollVo(activityEnrollVo);
        ActivityEnroll activityEnroll = BeanKit.convert(new ActivityEnroll(), activityEnrollVo);
        activityEnroll.setActivityId(activityEnrollVo.getActivityVo().getActivityId());
        activityEnroll.setMemberId(activityEnrollVo.getMerchantVo().getMemberId());
        activityEnroll.setCreator(HttpUtils.getLoginUser().getUsername());
        activityEnroll.setStatus(ActivityEnrollStatus.UNABLE.getCode());
        activityEnroll.setGmtActivityStart(activityEnrollVo.getGmtActivityStart());
        activityEnroll.setGmtActivityEnd(activityEnrollVo.getGmtActivityEnd());
        activityEnroll.setGmtCreate(new Date());
        Long activityEnrollId = (Long)jdbcDao.insert(activityEnroll);
        //添加报名分组
        int ord = 0;
        for (EnrollProductVo enrollProductVo : activityEnrollVo.getEnrollProductVos()) {
            EnrollProduct enrollProduct = BeanKit.convert(new EnrollProduct(),enrollProductVo);
            enrollProduct.setActivityEnrollId(activityEnrollId);
            enrollProduct.setOrd(ord);
            jdbcDao.insert(enrollProduct);
            ord++;
        }
    }

    /**
     * 验证报名单信息
     * @param activityEnrollVo
     */
    private void validateActivityEnrollVo(ActivityEnrollVo activityEnrollVo) {
        Verifier.init().notEmpty(activityEnrollVo.getActivityVo(),"活动").notEmpty(activityEnrollVo.getActivityVo().getName(), "活动")
                .notEmpty(activityEnrollVo.getMerchantVo(),"商家").notEmpty(activityEnrollVo.getMerchantVo().getMemberName(), "商家")
                .notEmpty(activityEnrollVo.getGmtBegin(),"报名开始时间").notEmpty(activityEnrollVo.getGmtEnd(),"报名截至时间")
                .notEmpty(activityEnrollVo.getTitle(), "标题").notEmpty(activityEnrollVo.getAddress(), "活动地点").validate();
        if(!validateActivity(activityEnrollVo)){
            throw new ImesneException("报名单活动不存在");
        }
        if(!validateMember(activityEnrollVo)){
            throw new ImesneException("报名单商家不存在");
        }
        validateEnrollProducts(activityEnrollVo);

    }

    /**
     * 验证报名单分组是否符合要求
     * @param activityEnrollVo
     */
    private void validateEnrollProducts(ActivityEnrollVo activityEnrollVo) {
        List<EnrollProductVo> list = activityEnrollVo.getEnrollProductVos();
        if(CollectionUtils.isEmpty(list)||StringUtils.isBlank(list.get(0).getName())){
            throw new ImesneException("报名单至少包含一个报名分组");
        }
        Set<String> enrollProductVoNames = new HashSet<>();
        for (EnrollProductVo enrollProductVo : list) {
            validateEnrollProductVo(enrollProductVo);
            if(enrollProductVoNames.contains(enrollProductVo.getName())){
                throw new ImesneException("报名分组名不可重复");
            }
            enrollProductVoNames.add(enrollProductVo.getName());
        }
    }
    private void validateEnrollProductVo(EnrollProductVo enrollProductVo){
        Verifier.init().notEmpty(enrollProductVo.getName(), "报名分组名称").notEmpty(enrollProductVo.getQuantity(), "报名分组人数");
    }

    /**
     * 验证报名单中的商家信息
     * @param activityEnrollVo
     * @return
     */
    public boolean validateMember(ActivityEnrollVo activityEnrollVo) {
        Select<Merchant> merchantSelect = jdbcDao.createSelect(Merchant.class).where("1", 1);
        merchantSelect.and("memberName", activityEnrollVo.getMerchantVo().getMemberName());
        Merchant merchant = merchantSelect.singleResult();
        if(merchant==null){
            return false;
        }
        activityEnrollVo.getMerchantVo().setMemberId(merchant.getMemberId());
        return true;
    }

    /**
     * 验证报名单中的活动信息
     * @param activityEnrollVo
     * @return
     */
    public boolean validateActivity(ActivityEnrollVo activityEnrollVo) {
        //判断活动是否存在
        Select<Activity> activitySelect = jdbcDao.createSelect(Activity.class).where("1",1);
        activitySelect.and("name", activityEnrollVo.getActivityVo().getName());
        Activity activity = activitySelect.singleResult();
        if(activity==null){
            return false;
        }
//        //判断该活动是否已经被其他报名单使用过
//        Select<ActivityEnroll> activityEnrollSelect = jdbcDao.createSelect(ActivityEnroll.class).where("1", 1);
//        activityEnrollSelect.and("activityId", activity.getActivityId());
//        if(activityEnrollVo.getActivityEnrollId()!=null){
//            activityEnrollSelect.and("activityEnrollId","!=",new Object[]{activityEnrollVo.getActivityEnrollId()});
//        }
//        ActivityEnroll activityEnroll = activityEnrollSelect.singleResult();
//        if(activityEnroll!=null){
//            return false;
//        }
        activityEnrollVo.getActivityVo().setActivityId(activity.getActivityId());
        return true;
    }

    @Override
    public void update(ActivityEnrollVo activityEnrollVo) {
        ActivityEnroll activityEnroll = findPoById(activityEnrollVo.getActivityEnrollId());
        validateCanModify(activityEnroll);
        validateActivityEnrollVo(activityEnrollVo);
        mergeVoToPo(activityEnroll, activityEnrollVo);
        jdbcDao.update(activityEnroll);
        //更新分组
        List<EnrollProductVo> oldEnrollProductVos = findEnrollProductVoListByActivityEnrollId(activityEnrollVo.getActivityEnrollId());
        Set<Long> oldEnrollProductIds = new HashSet<>();
        for (EnrollProductVo oldEnrollProductVo : oldEnrollProductVos) {
            oldEnrollProductIds.add(oldEnrollProductVo.getEnrollProductId());
        }
        int ord = 0;
        for (EnrollProductVo enrollProductVo : activityEnrollVo.getEnrollProductVos()) {
            //老分组更新
            if(oldEnrollProductIds.contains(enrollProductVo.getEnrollProductId())){
                oldEnrollProductIds.remove(enrollProductVo.getEnrollProductId());
            }else {
                //新分组添加
                EnrollProduct enrollProduct = BeanKit.convert(new EnrollProduct(),enrollProductVo);
                enrollProduct.setOrd(ord);
                enrollProduct.setActivityEnrollId(activityEnrollVo.getActivityEnrollId());
                jdbcDao.insert(enrollProduct);
            }
            ord++;
        }
        //删除已经被删除的分组
        for (Long oldEnrollProductId : oldEnrollProductIds) {
            Delete<EnrollProduct> enrollProductDelete = jdbcDao.createDelete(EnrollProduct.class).where("1",1);
            enrollProductDelete.and("enrollProductId",oldEnrollProductId);
            enrollProductDelete.execute();
        }
    }

    private void mergeVoToPo(ActivityEnroll activityEnroll, ActivityEnrollVo activityEnrollVo) {
        activityEnroll.setMemberId(activityEnrollVo.getMerchantVo().getMemberId());
        activityEnroll.setActivityId(activityEnrollVo.getActivityVo().getActivityId());
        activityEnroll.setAddress(activityEnrollVo.getAddress());
        activityEnroll.setGmtEnd(activityEnrollVo.getGmtEnd());
        activityEnroll.setTitle(activityEnrollVo.getTitle());
        activityEnroll.setMemo(activityEnrollVo.getMemo());
        activityEnroll.setGmtActivityStart(activityEnrollVo.getGmtActivityStart());
        activityEnroll.setGmtActivityEnd(activityEnrollVo.getGmtActivityEnd());
    }

    private void validateCanModify(ActivityEnroll activityEnroll){
        if(!StringUtils.equals(activityEnroll.getStatus(),ActivityEnrollStatus.UNABLE.getCode())){
            throw new ImesneException("报名单已启动，无法修改");
        }
    }

    @Override
    public ActivityEnrollVo findById(Long activityEnrollId) {
        ActivityEnroll activityEnroll = findPoById(activityEnrollId);
        ActivityEnrollVo activityEnrollVo = BeanKit.convert(new ActivityEnrollVo(), activityEnroll);
        if(activityEnroll.getMemberId()!=null){
            Select<Merchant> merchantSelect = jdbcDao.createSelect(Merchant.class).where("1", 1);
            merchantSelect.and("memberId",activityEnroll.getMemberId());
            Merchant merchant = merchantSelect.singleResult();
            if(merchant!=null){
                activityEnrollVo.setMerchantVo(BeanKit.convert(new MerchantVo(),merchant));
            }
        }
        if(activityEnroll.getActivityId()!=null){
            Select<Activity> activitySelect = jdbcDao.createSelect(Activity.class).where("1",1);
            activitySelect.and("activityId", activityEnroll.getActivityId());
            Activity activity = activitySelect.singleResult();
            if(activity!=null){
                activityEnrollVo.setActivityVo(BeanKit.convert(new ActivityVo(), activity));
            }
        }
        List<EnrollProductVo> enrollProductVos = findEnrollProductVoListByActivityEnrollId(activityEnrollId);
        for (EnrollProductVo enrollProductVo : enrollProductVos) {
            int count = countEnrollProductQuntity(enrollProductVo.getEnrollProductId());
            enrollProductVo.setEnrolledQuantity(count);
        }
        activityEnrollVo.setEnrollProductVos(enrollProductVos);
        return activityEnrollVo;
    }

    @Override
    public List<ActivityEnrollVo> findByActivityId(Long activityId) {
        Select<ActivityEnroll> activityEnrollSelect = jdbcDao.createSelect(ActivityEnroll.class).where("1", 1);
        activityEnrollSelect.and("activityId",activityId);
        activityEnrollSelect.and("status", "!=", new Object[]{ActivityEnrollStatus.UNABLE.getCode()});
        activityEnrollSelect.and("status","!=",new Object[]{ActivityEnrollStatus.COMPLETE.getCode()});
        List<ActivityEnroll> activityEnrolls =activityEnrollSelect.list();
        if(CollectionUtils.isEmpty(activityEnrolls)){
            return new ArrayList<>();
        }
        List<ActivityEnrollVo> activityEnrollVos = BeanKit.convert(ActivityEnrollVo.class, activityEnrolls);
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd hh:mm");
        for (ActivityEnrollVo activityEnrollVo : activityEnrollVos) {
            activityEnrollVo.setGmtEndStr(formatter.format(activityEnrollVo.getGmtEnd()));
            if(activityEnrollVo.getMemberId()!=null){
                Select<Merchant> merchantSelect = jdbcDao.createSelect(Merchant.class).where("1", 1);
                merchantSelect.and("memberId",activityEnrollVo.getMemberId());
                Merchant merchant = merchantSelect.singleResult();
                if(merchant!=null){
                    activityEnrollVo.setMerchantVo(BeanKit.convert(new MerchantVo(), merchant));
                }
            }
            List<EnrollProductVo> enrollProductVos = findEnrollProductVoListByActivityEnrollId(activityEnrollVo.getActivityEnrollId());
            for (EnrollProductVo enrollProductVo : enrollProductVos) {
                int left = enrollProductVo.getQuantity()-countEnrollProductQuntity(enrollProductVo.getEnrollProductId());
                left = left<0?0:left;
                enrollProductVo.setLeft(left);
            }
            activityEnrollVo.setEnrollProductVos(enrollProductVos);
        }
        return activityEnrollVos;
    }

    private int countEnrollProductQuntity(Long enrollProductId){
        Select<EnrollNamelist> enrollNamelistSelect = jdbcDao.createSelect(EnrollNamelist.class).where("1", 1);
        enrollNamelistSelect.and("enrollProductId", enrollProductId);
        List<EnrollNamelist> list = enrollNamelistSelect.list();
        int result = 0;
        for (EnrollNamelist enrollNamelist : list) {
            result += enrollNamelist.getQuantity();
        }
        return result;
    }

    private List<EnrollProductVo> findEnrollProductVoListByActivityEnrollId(Long activityEnrollId) {
        Select<EnrollProduct> enrollProductSelect = jdbcDao.createSelect(EnrollProduct.class).where("1", 1);
        enrollProductSelect.and("activityEnrollId",activityEnrollId);
        enrollProductSelect.orderBy("ord").asc();
        List<EnrollProduct> list = enrollProductSelect.list();
        List<EnrollProductVo> enrollProductVos = BeanKit.convert(EnrollProductVo.class,list);
        return enrollProductVos;
    }

    @Override
    public void enable(Long activityEnrollId) {
        ActivityEnroll activityEnroll = findPoById(activityEnrollId);
        if(!StringUtils.equals(activityEnroll.getStatus(),ActivityEnrollStatus.UNABLE.getCode())){
            throw new ImesneException("该报名单不是未启动状态，无法启动");
        }
        activityEnroll.setGmtBegin(new Date());
        activityEnroll.setStatus(ActivityEnrollStatus.ENROLLMENT.getCode());
        jdbcDao.update(activityEnroll);
    }

    @Override
    public void deleteByIds(Long[] activityEnrollIds) {
        for (Long activityEnrollId : activityEnrollIds) {
            ActivityEnroll activityEnroll = findPoById(activityEnrollId);
            if(StringUtils.equals(activityEnroll.getStatus(),ActivityEnrollStatus.COMPLETE.getCode())){
                throw new ImesneException("已完成的报名单无法删除");
            }
            Select<EnrollProduct> enrollProductSelect = jdbcDao.createSelect(EnrollProduct.class).where("1",1);
            enrollProductSelect.and("activityEnrollId",activityEnrollId);
            List<EnrollProduct> enrollProducts = enrollProductSelect.list();
            for (EnrollProduct enrollProduct : enrollProducts) {
                Select<EnrollNamelist> enrollNamelistSelect = jdbcDao.createSelect(EnrollNamelist.class).where("1",1);
                enrollNamelistSelect.and("enrollProductId",enrollProduct.getEnrollProductId());
                EnrollNamelist enrollNamelist = enrollNamelistSelect.singleResult();
                if(enrollNamelist!=null){
                    throw new ImesneException("报名单已有人报名，无法删除");
                }
                jdbcDao.delete(enrollProduct);
            }
            jdbcDao.delete(activityEnroll);
        }
    }

    @Override
    public void addEnrollProductVo(ActivityEnrollVo activityEnrollVo) {
        List<EnrollProductVo> enrollProductVos = activityEnrollVo.getEnrollProductVos();
        if(CollectionUtils.isEmpty(enrollProductVos)){
            enrollProductVos = new ArrayList<>();
            activityEnrollVo.setEnrollProductVos(enrollProductVos);
        }
        EnrollProductVo enrollProductVo = new EnrollProductVo();
        enrollProductVos.add(enrollProductVo);
    }

    @Override
    public PageList<EnrollNamelistVo> namePageList(EnrollNamelistVo enrollNamelistVo, ActivityEnrollVo activityEnrollVo) {
        List<EnrollProductVo> enrollProductVos = activityEnrollVo.getEnrollProductVos();
        Map<Long,String> enrollProductNameMap = new HashMap<>();
        for (EnrollProductVo enrollProductVo : enrollProductVos) {
            enrollProductNameMap.put(enrollProductVo.getEnrollProductId(),enrollProductVo.getName());
        }
        Select<EnrollNamelist> enrollNamelistSelect = jdbcDao.createSelect(EnrollNamelist.class).where("1", 1);
        if(StringUtils.isNotBlank(enrollNamelistVo.getEnrollProductName())){
            boolean flag = false;
            for (EnrollProductVo enrollProductVo : enrollProductVos) {
                if(StringUtils.equals(enrollProductVo.getName(),enrollNamelistVo.getEnrollProductName())){
                    flag = true;
                    enrollNamelistSelect.and("enrollProductId",enrollProductVo.getEnrollProductId());
                    break;
                }
            }
            //如果分组名不存在，返回空集合
            if(!flag){
                return new PageList<>();
            }
        }else {
            if(CollectionUtils.isNotEmpty(enrollProductVos)){
                enrollNamelistSelect.and().begin();
                for (int i=0;i<enrollProductVos.size();i++) {
                    EnrollProductVo enrollProduct = enrollProductVos.get(i);
                    if(i==0){
                        enrollNamelistSelect.condition("enrollProductId",enrollProduct.getEnrollProductId());
                    }else {
                        enrollNamelistSelect.or("enrollProductId",enrollProduct.getEnrollProductId());
                    }
                }
                enrollNamelistSelect.end();
            }else {
                return new PageList<>();
            }
        }
        if(StringUtils.isNotBlank(enrollNamelistVo.getName())){
            enrollNamelistSelect.and("name","like",new Object[]{"%"+enrollNamelistVo.getName()+"%"});
        }
        if(StringUtils.isNoneBlank(enrollNamelistVo.getMobile())){
            enrollNamelistSelect.and("mobile","like",new Object[]{"%"+enrollNamelistVo.getMobile()+"%"});
        }
        if(StringUtils.isNotBlank(enrollNamelistVo.getStatus())){
            enrollNamelistSelect.and("status",enrollNamelistVo.getStatus());
        }
        PageList<EnrollNamelist> enrollNamelists = enrollNamelistSelect.pageList(enrollNamelistVo);
        List<EnrollNamelistVo> enrollNamelistVos = BeanKit.convert(EnrollNamelistVo.class, enrollNamelists);
        PageList<EnrollNamelistVo> result = new PageList<>(enrollNamelistVos,enrollNamelists.getPager());
        for (EnrollNamelistVo namelistVo : result) {
            namelistVo.setEnrollProductName(enrollProductNameMap.get(namelistVo.getEnrollProductId()));
            namelistVo.setAttendance(attendanceService.getAtendencePer(namelistVo.getWeixin()));
        }
        return result;
    }

    @Override
    public void enroll(EnrollNamelistVo enrollNamelistVo) {
        Verifier.init().notEmpty(enrollNamelistVo.getName(),"姓名").notEmpty(enrollNamelistVo.getMobile(),"联系方式")
        .notEmpty(enrollNamelistVo.getWeixin(),"微信号");
        Date now = new Date();
        Select<EnrollProduct> enrollProductSelect = jdbcDao.createSelect(EnrollProduct.class).where("1",1);
        enrollProductSelect.and("enrollProductId",enrollNamelistVo.getEnrollProductId());
        EnrollProduct enrollProduct = enrollProductSelect.singleResult();
        if(enrollProduct==null){
            throw new ImesneException("报名分组不存在");
        }
        int left = enrollProduct.getQuantity()-countEnrollProductQuntity(enrollProduct.getEnrollProductId());
        if(left<=0){
            throw new ImesneException("余票不足");
        }
        ActivityEnroll activityEnroll = findPoById(enrollProduct.getActivityEnrollId());
        if(!StringUtils.equals(activityEnroll.getStatus(),ActivityEnrollStatus.ENROLLMENT.getCode())||(activityEnroll.getGmtEnd().getTime()-now.getTime())<0){
            throw new ImesneException("报名不存在或已结束");
        }
        EnrollNamelist enrollNamelist = BeanKit.convert(new EnrollNamelist(),enrollNamelistVo);
        enrollNamelist.setStatus(EnrollNamelistStatus.ENROLLED.getCode());
        enrollNamelist.setGmtEnroll(now);
        enrollNamelist.setQuantity(1);
        jdbcDao.insert(enrollNamelist);
    }

    @Override
    public PageList<EnrollNamelistVo> myEnrollPageList(EnrollNamelistVo enrollNamelistVo) {
        Select<EnrollNamelist> enrollNamelistSelect = jdbcDao.createSelect(EnrollNamelist.class).where("1", 1);
        enrollNamelistSelect.and("weixin", enrollNamelistVo.getWeixin());
        enrollNamelistSelect.orderBy("gmtEnroll").desc();
        PageList<EnrollNamelist> enrollNamelists = enrollNamelistSelect.pageList(enrollNamelistVo);
        List<EnrollNamelistVo> enrollNamelistVos = BeanKit.convert(EnrollNamelistVo.class, enrollNamelists);
        PageList<EnrollNamelistVo> result = new PageList<>(enrollNamelistVos,enrollNamelists.getPager());
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd hh:mm");
        for (EnrollNamelistVo namelistVo : result) {
            namelistVo.setStatus(getEnrollNamelistStatusValueByCode(namelistVo.getStatus()));

            Select<EnrollProduct> enrollProductSelect = jdbcDao.createSelect(EnrollProduct.class).where("1", 1);
            enrollProductSelect.and("enrollProductId", namelistVo.getEnrollProductId());
            EnrollProduct enrollProduct = enrollProductSelect.singleResult();
            namelistVo.setEnrollProductVo(BeanKit.convert(new EnrollProductVo(), enrollProduct));

            Select<ActivityEnroll> activityEnrollSelect = jdbcDao.createSelect(ActivityEnroll.class).where("1", 1);
            activityEnrollSelect.and("activityEnrollId", enrollProduct.getActivityEnrollId());
            ActivityEnroll activityEnroll = activityEnrollSelect.singleResult();
            ActivityEnrollVo activityEnrollVo = BeanKit.convert(new ActivityEnrollVo(), activityEnroll);
            Select<Merchant> merchantSelect = jdbcDao.createSelect(Merchant.class).where("1", 1);
            merchantSelect.and("memberId",activityEnroll.getMemberId());
            Merchant merchant = merchantSelect.singleResult();
            activityEnrollVo.setMerchantVo(BeanKit.convert(new MerchantVo(),merchant));
            namelistVo.setActivityEnrollVo(activityEnrollVo);

            Select<Activity> activitySelect = jdbcDao.createSelect(Activity.class).where("1",1);
            activitySelect.and("activityId", activityEnroll.getActivityId());
            Activity activity = activitySelect.singleResult();
            ActivityVo activityVo = BeanKit.convert(new ActivityVo(),activity);
            activityVo.setBeginDateStr(formatter.format(activityVo.getBeginDate()));
            activityVo.setEndDateStr(formatter.format(activity.getEndDate()));

            namelistVo.setActivityVo(activityVo);
        }
        return result;
    }

    @Override
    public int updateActivityEnrollStatus() {
        Update<ActivityEnroll> activityEnrollUpdate = jdbcDao.createUpdate(ActivityEnroll.class).where("1", 1);
        activityEnrollUpdate.and("status", ActivityEnrollStatus.ENROLLMENT.getCode());
        activityEnrollUpdate.and("gmtEnd", "<", new Object[]{new Date()});
        activityEnrollUpdate.set("status", ActivityEnrollStatus.STOPPED.getCode());
        int result = activityEnrollUpdate.execute();
        return result;
    }

    @Override
    public void sign(Long[] enrollNamelistIds) {
        for (Long enrollNamelistId : enrollNamelistIds) {
            EnrollNamelist enrollNamelist = findEnrollNamelistById(enrollNamelistId);
            if(enrollNamelist==null){
                throw new ImesneException("不存在的报名信息");
            }
            if(!StringUtils.equals(enrollNamelist.getStatus(),EnrollNamelistStatus.ENROLLED.getCode())){
                throw new ImesneException("只有已报名状态的才能签到");
            }
            enrollNamelist.setStatus(EnrollNamelistStatus.SIGNED.getCode());
            jdbcDao.update(enrollNamelist);
        }
    }

    @Override
    public void cancel(Long[] enrollNamelistIds) {
        for (Long enrollNamelistId : enrollNamelistIds) {
            EnrollNamelist enrollNamelist = findEnrollNamelistById(enrollNamelistId);
            if(enrollNamelist==null){
                throw new ImesneException("不存在的报名信息");
            }
            if(StringUtils.equals(enrollNamelist.getStatus(),EnrollNamelistStatus.SIGNED.getCode())){
                throw new ImesneException("已经签到的用户无法取消");
            }
            if(StringUtils.equals(enrollNamelist.getStatus(),EnrollNamelistStatus.CANCELLED.getCode())){
                throw new ImesneException("已经取消过的报名信息无法再取消");
            }
            if(StringUtils.equals(enrollNamelist.getStatus(),EnrollNamelistStatus.UNCOMMITTED.getCode())){
                throw new ImesneException("报名结算后无法再取消或退款");
            }
            enrollNamelist.setStatus(EnrollNamelistStatus.CANCELLED.getCode());
            enrollNamelist.setQuantity(0);
            jdbcDao.update(enrollNamelist);
        }
    }

    @Override
    public void exportExcel(List<EnrollNamelistVo> enrollNamelistVos, HttpServletResponse response) {
        try {
            ExcelUtils.createExcelWorkbood(uploadFilePath,response,enrollNamelistVos,"报名人员单");
        } catch (IOException e) {
            throw new ImesneException("导出失败");
        }
    }

    @Override
    public void complete(Long[] activityEnrollIds) {
        for (Long activityEnrollId : activityEnrollIds) {
            Select<ActivityEnroll> activityEnrollSelect = jdbcDao.createSelect(ActivityEnroll.class).where("1", 1);
            activityEnrollSelect.and("activityEnrollId", activityEnrollId);
            ActivityEnroll activityEnroll = activityEnrollSelect.singleResult();
            if(!StringUtils.equals(activityEnroll.getStatus(),ActivityEnrollStatus.STOPPED.getCode())){
                throw new ImesneException("只有已经截止的报名单才能完成");
            }
            Select<EnrollProduct> enrollProductSelect = jdbcDao.createSelect(EnrollProduct.class).where("1", 1);
            enrollProductSelect.and("activityEnrollId",activityEnrollId);
            List<EnrollProduct> enrollProductList = enrollProductSelect.list();
            Map<String,Map<String,Integer>> countMap = new HashMap<>();
            for (EnrollProduct enrollProduct : enrollProductList) {
                Select<EnrollNamelist> enrollNamelistSelect = jdbcDao.createSelect(EnrollNamelist.class).where("1",1);
                enrollNamelistSelect.and("enrollProductId",enrollProduct.getEnrollProductId());
                List<EnrollNamelist> enrollNamelists = enrollNamelistSelect.list();
                for (EnrollNamelist enrollNamelist : enrollNamelists) {
                    String weixin = enrollNamelist.getWeixin();
                    Map<String,Integer> map = countMap.get(enrollNamelist.getWeixin());
                    if(map==null){
                        map = new HashMap<>();
                        map.put("signed",0);
                        map.put("total",0);
                        countMap.put(weixin,map);
                    }
                    if(StringUtils.equals(enrollNamelist.getStatus(),EnrollNamelistStatus.SIGNED.getCode())){
                        int signedCount = map.get("signed")+1;
                        map.put("signed",signedCount);
                    }
                    if(!StringUtils.equals(enrollNamelist.getStatus(),EnrollNamelistStatus.CANCELLED.getCode())){
                        int totalCount = map.get("total")+1;
                        map.put("total", totalCount);
                    }
                }
                //将已报名但是未签到的名单更新为未参加
                Update<EnrollNamelist> enrollNamelistUpdate = jdbcDao.createUpdate(EnrollNamelist.class).where("1",1);
                enrollNamelistUpdate.and("enrollProductId",enrollProduct.getEnrollProductId());
                enrollNamelistUpdate.and("status",EnrollNamelistStatus.ENROLLED.getCode());
                enrollNamelistUpdate.set("status", EnrollNamelistStatus.UNCOMMITTED.getCode());
                enrollNamelistUpdate.execute();
            }
            DecimalFormat df = new DecimalFormat("######0.00");
            Date date = new Date();
            for (Map.Entry<String, Map<String, Integer>> stringMapEntry : countMap.entrySet()) {
                String weixin = stringMapEntry.getKey();
                Map<String,Integer> map = stringMapEntry.getValue();
                if(map.get("signed")==0&&map.get("total")==0){
                    continue;
                }
                Attendance attendance = attendanceService.findByWeixin(weixin);
                if(attendance!=null){
                    attendance.setAttendTime(attendance.getAttendTime() + map.get("signed"));
                    attendance.setTotalTime(attendance.getTotalTime() + map.get("total"));
                    double attendancePercent = (double)attendance.getAttendTime()/attendance.getTotalTime();
                    df.format(attendancePercent);
                    if(attendancePercent>1){
                        throw new ImesneException("计算出错，出勤数大于报名数");
                    }
                    attendance.setAttendance(attendancePercent);
                    attendance.setGmtModify(date);
                    jdbcDao.update(attendance);
                }else {
                    attendance = new Attendance();
                    attendance.setWeixin(weixin);
                    attendance.setGmtModify(date);
                    //初始默认有三次
                    attendance.setTotalTime(map.get("total")+3);
                    attendance.setAttendTime(map.get("signed")+3);
                    double attendancePercent = (double)attendance.getAttendTime()/attendance.getTotalTime();
                    df.format(attendancePercent);
                    if(attendancePercent>1){
                        throw new ImesneException("计算出错，出勤数大于报名数");
                    }
                    attendance.setAttendance(attendancePercent);
                    jdbcDao.insert(attendance);
                }
            }
            activityEnroll.setStatus(ActivityEnrollStatus.COMPLETE.getCode());
            jdbcDao.update(activityEnroll);
        }
    }

    @Override
    public EnrollNamelistVo getEnrollNamelistDetailById(Long enrollNamelistId) {
        EnrollNamelistVo enrollNamelistVo = BeanKit.convert(new EnrollNamelistVo(), findEnrollNamelistById(enrollNamelistId));
        EnrollProductVo enrollProductVo = BeanKit.convert(new EnrollProductVo(), findEnrollProductById(enrollNamelistVo.getEnrollProductId()));
        enrollNamelistVo.setEnrollProductVo(enrollProductVo);
        ActivityEnrollVo activityEnrollVo = findById(enrollProductVo.getActivityEnrollId());
        enrollNamelistVo.setActivityEnrollVo(activityEnrollVo);
        enrollNamelistVo.setStatus(getEnrollNamelistStatusValueByCode(enrollNamelistVo.getStatus()));
        enrollNamelistVo.setAttendance(attendanceService.getAtendencePer(enrollNamelistVo.getWeixin()));
        //设置短信列表
        Select<NamelistSmsRela> namelistSmsRelaSelect = jdbcDao.createSelect(NamelistSmsRela.class).where("1", 1);
        namelistSmsRelaSelect.and("enrollNamelistId", enrollNamelistId);
        List<NamelistSmsRela> namelistSmsRelas = namelistSmsRelaSelect.list();
        List<ProductSmsVo> productSmsVos = new ArrayList<>();
        for (NamelistSmsRela namelistSmsRela : namelistSmsRelas) {
            productSmsVos.add(productSmsService.findById(namelistSmsRela.getProductSmsId()));
        }
        enrollNamelistVo.setProductSmsVos(productSmsVos);
        return enrollNamelistVo;
    }

    @Override
    public PageList<ActivityVo> mobilePageListActivityVo(ActivityEnrollVo activityEnrollVo) {
        StringBuilder sql = new StringBuilder("SELECT DISTINCT b.ACTIVITY_ID FROM (SELECT ACTIVITY_ID,GMT_CREATE,STATUS FROM iwl_activity_enroll WHERE STATUS !='complete' and STATUS != 'unable' ");
        Object[] objects = new Object[]{};
        if(activityEnrollVo.getBeginTime()!=null&&activityEnrollVo.getEndTime()!=null){
            sql.append("AND (GMT_END >= ? AND GMT_BEGIN <= ?) ");
            objects = new Object[]{activityEnrollVo.getBeginTime(),activityEnrollVo.getEndTime()};
        }
        sql.append("ORDER BY STATUS ASC ,GMT_CREATE DESC ) as b");
        PageList<Map<String,Long>> pageList= (PageList<Map<String,Long>>)jdbcDao.createNativeExecutor()
                .command(sql.toString()).parameters(objects)
                .pageList(activityEnrollVo);
        List<ActivityVo> activityVos = new ArrayList<>();
        for (Map<String, Long> map : pageList) {
            Long activityId = map.get("ACTIVITY_ID");
            Select<Activity> activitySelect = jdbcDao.createSelect(Activity.class).where("1",1);
            activitySelect.and("activityId",activityId);
            activityVos.add(BeanKit.convert(new ActivityVo(),activitySelect.singleResult()));
        }
        for (ActivityVo activityVo : activityVos) {
            activityVo.setFirstPicUrl(activityService.findActivityFirstPicUrl(activityVo.getActivityId()));
        }
        PageList<ActivityVo> result = new PageList<>(activityVos,pageList.getPager());
        return result;
    }

    @Override
    public PageList<ActivityEnrollVo> nameFilter(ActivityEnrollVo activityEnrollVo) {
        Select<ActivityEnroll> activityEnrollSelect = jdbcDao.createSelect(ActivityEnroll.class).where("1", 1);
        activityEnrollSelect.and("title","like",new Object[]{"%"+activityEnrollVo.getTitle()+"%"} );
        PageList<ActivityEnroll> activityEnrolls = activityEnrollSelect.pageList(activityEnrollVo);
        List<ActivityEnrollVo> activityEnrollVos = BeanKit.convert(ActivityEnrollVo.class, activityEnrolls);
        PageList<ActivityEnrollVo> result = new PageList<>(activityEnrollVos,activityEnrolls.getPager());
        return result;
    }

    private EnrollProduct findEnrollProductById(Long enrollProductId){
        Select<EnrollProduct> enrollProductSelect = jdbcDao.createSelect(EnrollProduct.class).where("1", 1);
        enrollProductSelect.and("enrollProductId", enrollProductId);
        return enrollProductSelect.singleResult();
    }

    private EnrollNamelist findEnrollNamelistById(Long enrollNamelistId){
        Select<EnrollNamelist> enrollNamelistSelect = jdbcDao.createSelect(EnrollNamelist.class).where("1",1);
        enrollNamelistSelect.and("enrollNamelistId", enrollNamelistId);
        return enrollNamelistSelect.singleResult();
    }


    private ActivityEnroll findPoById(Long activityEnrollId){
        Select<ActivityEnroll> activityEnrollSelect = jdbcDao.createSelect(ActivityEnroll.class).where("1", 1);
        activityEnrollSelect.and("activityEnrollId", activityEnrollId);
        return activityEnrollSelect.singleResult();
    }

    private String getEnrollNamelistStatusValueByCode(String code){
        for (EnrollNamelistStatus enrollNamelistStatus:EnrollNamelistStatus.values()){
            if(StringUtils.equals(enrollNamelistStatus.getCode(),code)){
                return enrollNamelistStatus.getDesc();
            }
        }
        return "";
    }
}
